import {
	IExecuteFunctions,
	INodeExecutionData,
	INodeType,
	INodeTypeDescription,
	NodeOperationError,
} from 'n8n-workflow';

// 全局数据存储，按工作流执行ID分组
const workflowDataStores = new Map<string, Map<string, any>>();

// 工作流执行完成时的清理回调
const workflowCleanupCallbacks = new Map<string, Set<() => void>>();

// 设置工作流清理机制
function setupWorkflowCleanup(storeKey: string, _executionId: string) {
	const cleanup = () => {
		if (workflowDataStores.has(storeKey)) {
			const dataStore = workflowDataStores.get(storeKey)!;
			console.log(`清理工作流数据存储: ${storeKey}, 包含 ${dataStore.size} 个数据项`);
			workflowDataStores.delete(storeKey);
		}
		if (workflowCleanupCallbacks.has(storeKey)) {
			workflowCleanupCallbacks.delete(storeKey);
		}
	};

	// 添加到清理回调集合
	workflowCleanupCallbacks.get(storeKey)!.add(cleanup);

	// 设置清理机制
	// 由于n8n的执行上下文限制，我们使用基于时间的清理策略

	// 1. 短期清理 - 5分钟后检查并清理（适用于短期工作流）
	setTimeout(() => {
		// 检查存储是否仍在使用
		if (workflowDataStores.has(storeKey)) {
			const dataStore = workflowDataStores.get(storeKey)!;
			const now = new Date();
			let hasRecentActivity = false;

			// 检查是否有最近的活动（最近1分钟内更新的数据）
			for (const [, item] of dataStore) {
				const updatedAt = new Date(item.updatedAt);
				if (now.getTime() - updatedAt.getTime() < 60 * 1000) {
					hasRecentActivity = true;
					break;
				}
			}

			// 如果没有最近活动，执行清理
			if (!hasRecentActivity) {
				console.log(`执行短期清理: ${storeKey} (无最近活动)`);
				cleanup();
			}
		}
	}, 5 * 60 * 1000); // 5分钟

	// 2. 长期清理 - 30分钟后强制清理
	setTimeout(() => {
		console.log(`执行强制清理: ${storeKey} (超时清理)`);
		cleanup();
	}, 30 * 60 * 1000); // 30分钟
}

// 处理设置操作
async function handleSetOperation(this: IExecuteFunctions, itemIndex: number, dataStore: Map<string, any>) {
	const key = this.getNodeParameter('key', itemIndex) as string;
	const value = this.getNodeParameter('value', itemIndex);
	const includeMetadata = this.getNodeParameter('includeMetadata', itemIndex, false) as boolean;

	if (!key) {
		throw new NodeOperationError(this.getNode(), '键名不能为空', { itemIndex });
	}

	// 创建数据项，包含元数据
	const dataItem = {
		value,
		createdAt: new Date().toISOString(),
		updatedAt: new Date().toISOString(),
		nodeId: this.getNode().id,
		nodeName: this.getNode().name,
	};

	// 如果键已存在，保留创建时间
	if (dataStore.has(key)) {
		const existingItem = dataStore.get(key);
		dataItem.createdAt = existingItem.createdAt;
	}

	dataStore.set(key, dataItem);

	const result: any = {
		operation: 'set',
		key,
		success: true,
		message: `数据已成功存储到键 '${key}'`,
	};

	if (includeMetadata) {
		result.metadata = {
			createdAt: dataItem.createdAt,
			updatedAt: dataItem.updatedAt,
			nodeId: dataItem.nodeId,
			nodeName: dataItem.nodeName,
		};
	}

	return result;
}

// 处理获取操作
async function handleGetOperation(this: IExecuteFunctions, itemIndex: number, dataStore: Map<string, any>) {
	const key = this.getNodeParameter('key', itemIndex) as string;
	const defaultValue = this.getNodeParameter('defaultValue', itemIndex, null);
	const includeMetadata = this.getNodeParameter('includeMetadata', itemIndex, false) as boolean;

	if (!key) {
		throw new NodeOperationError(this.getNode(), '键名不能为空', { itemIndex });
	}

	const result: any = {
		operation: 'get',
		key,
	};

	if (dataStore.has(key)) {
		const dataItem = dataStore.get(key);
		result.value = dataItem.value;
		result.success = true;
		result.found = true;

		if (includeMetadata) {
			result.metadata = {
				createdAt: dataItem.createdAt,
				updatedAt: dataItem.updatedAt,
				nodeId: dataItem.nodeId,
				nodeName: dataItem.nodeName,
			};
		}
	} else {
		result.value = defaultValue;
		result.success = true;
		result.found = false;
		result.message = `键 '${key}' 不存在，返回默认值`;
	}

	return result;
}

// 处理删除操作
async function handleDeleteOperation(this: IExecuteFunctions, itemIndex: number, dataStore: Map<string, any>) {
	const key = this.getNodeParameter('key', itemIndex) as string;

	if (!key) {
		throw new NodeOperationError(this.getNode(), '键名不能为空', { itemIndex });
	}

	const existed = dataStore.has(key);
	if (existed) {
		dataStore.delete(key);
	}

	return {
		operation: 'delete',
		key,
		success: true,
		existed,
		message: existed ? `键 '${key}' 已删除` : `键 '${key}' 不存在`,
	};
}

// 处理列表操作
async function handleListOperation(this: IExecuteFunctions, dataStore: Map<string, any>) {
	const includeMetadata = this.getNodeParameter('includeMetadata', 0, false) as boolean;

	const keys = Array.from(dataStore.keys());
	const result: any = {
		operation: 'list',
		keys,
		count: keys.length,
		success: true,
	};

	if (includeMetadata) {
		result.items = {};
		for (const key of keys) {
			const dataItem = dataStore.get(key);
			result.items[key] = {
				createdAt: dataItem.createdAt,
				updatedAt: dataItem.updatedAt,
				nodeId: dataItem.nodeId,
				nodeName: dataItem.nodeName,
			};
		}
	}

	return result;
}

// 处理清空操作
async function handleClearOperation(this: IExecuteFunctions, dataStore: Map<string, any>) {
	const count = dataStore.size;
	dataStore.clear();

	return {
		operation: 'clear',
		success: true,
		clearedCount: count,
		message: `已清空 ${count} 个数据项`,
	};
}

export class WorkflowDataStore implements INodeType {
	description: INodeTypeDescription = {
		displayName: '工作流数据存储',
		name: 'workflowDataStore',
		icon: 'fa:database',
		group: ['transform'],
		version: 1,
		subtitle: '={{$parameter["operation"] === "set" ? "设置: " + $parameter["key"] : "获取: " + $parameter["key"]}}',
		description: '在工作流执行期间提供数据共享，支持get/set操作，工作流结束时自动清理',
		defaults: {
			name: '工作流数据存储',
			color: '#FF6B6B',
		},
		inputs: ['main'],
		outputs: ['main'],
		properties: [
			{
				displayName: '操作',
				name: 'operation',
				type: 'options',
				noDataExpression: true,
				options: [
					{
						name: '设置数据',
						value: 'set',
						description: '在工作流数据存储中设置一个键值对',
						action: '设置数据到工作流存储',
					},
					{
						name: '获取数据',
						value: 'get',
						description: '从工作流数据存储中获取数据',
						action: '从工作流存储获取数据',
					},
					{
						name: '删除数据',
						value: 'delete',
						description: '从工作流数据存储中删除指定的键',
						action: '从工作流存储删除数据',
					},
					{
						name: '列出所有键',
						value: 'list',
						description: '列出工作流数据存储中的所有键',
						action: '列出工作流存储中的所有键',
					},
					{
						name: '清空存储',
						value: 'clear',
						description: '清空当前工作流的所有存储数据',
						action: '清空工作流存储',
					},
				],
				default: 'set',
			},
			{
				displayName: '键名',
				name: 'key',
				type: 'string',
				displayOptions: {
					hide: {
						operation: ['list', 'clear'],
					},
				},
				default: '',
				placeholder: '例如: userInfo, processedData, config',
				description: '数据存储的键名',
				required: true,
			},
			{
				displayName: '值',
				name: 'value',
				type: 'json',
				displayOptions: {
					show: {
						operation: ['set'],
					},
				},
				default: '',
				placeholder: '{"name": "张三", "age": 30}',
				description: '要存储的数据值，支持任何JSON格式的数据',
				required: true,
			},
			{
				displayName: '默认值',
				name: 'defaultValue',
				type: 'json',
				displayOptions: {
					show: {
						operation: ['get'],
					},
				},
				default: '',
				placeholder: '{"default": "value"}',
				description: '当键不存在时返回的默认值',
			},
			{
				displayName: '数据作用域',
				name: 'scope',
				type: 'options',
				options: [
					{
						name: '工作流级别',
						value: 'workflow',
						description: '数据在整个工作流执行期间共享',
					},
					{
						name: '执行级别',
						value: 'execution',
						description: '数据仅在当前执行实例中共享',
					},
				],
				default: 'workflow',
				description: '数据的共享作用域',
			},
			{
				displayName: '包含元数据',
				name: 'includeMetadata',
				type: 'boolean',
				displayOptions: {
					show: {
						operation: ['get', 'list'],
					},
				},
				default: false,
				description: '是否在结果中包含元数据信息（如创建时间、更新时间等）',
			},
		],
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const items = this.getInputData();
		const returnData: INodeExecutionData[] = [];

		// 获取工作流执行ID作为存储的命名空间
		const workflowId = this.getWorkflow().id;
		const executionId = this.getExecutionId();
		const operation = this.getNodeParameter('operation', 0) as string;
		const scope = this.getNodeParameter('scope', 0) as string;

		// 确保workflowId和executionId不为空
		if (!workflowId) {
			throw new NodeOperationError(this.getNode(), '无法获取工作流ID');
		}
		if (!executionId) {
			throw new NodeOperationError(this.getNode(), '无法获取执行ID');
		}

		// 根据作用域确定存储键
		const storeKey = scope === 'workflow' ? workflowId : `${workflowId}_${executionId}`;

		// 确保存储存在
		if (!workflowDataStores.has(storeKey)) {
			workflowDataStores.set(storeKey, new Map<string, any>());
		}

		const dataStore = workflowDataStores.get(storeKey)!;

		// 注册清理回调（仅在第一次访问时注册）
		if (!workflowCleanupCallbacks.has(storeKey)) {
			workflowCleanupCallbacks.set(storeKey, new Set());
			setupWorkflowCleanup(storeKey, executionId);
		}

		for (let i = 0; i < items.length; i++) {
			try {
				let result: any = {};

				switch (operation) {
					case 'set':
						result = await handleSetOperation.call(this, i, dataStore);
						break;
					case 'get':
						result = await handleGetOperation.call(this, i, dataStore);
						break;
					case 'delete':
						result = await handleDeleteOperation.call(this, i, dataStore);
						break;
					case 'list':
						result = await handleListOperation.call(this, dataStore);
						break;
					case 'clear':
						result = await handleClearOperation.call(this, dataStore);
						break;
					default:
						throw new NodeOperationError(
							this.getNode(),
							`不支持的操作: ${operation}`,
							{ itemIndex: i }
						);
				}

				returnData.push({
					json: {
						...items[i].json,
						...result,
					},
					pairedItem: { item: i },
				});
			} catch (error) {
				if (this.continueOnFail()) {
					returnData.push({
						json: {
							...items[i].json,
							error: error instanceof Error ? error.message : String(error),
							operation,
							success: false,
						},
						pairedItem: { item: i },
					});
				} else {
					throw error;
				}
			}
		}

		return [returnData];
	}
}

// 导出清理函数，供外部调用
export function cleanupWorkflowData(workflowId: string, executionId?: string) {
	const keys = Array.from(workflowDataStores.keys());
	
	for (const key of keys) {
		if (executionId) {
			// 清理特定执行的数据
			if (key === `${workflowId}_${executionId}`) {
				workflowDataStores.delete(key);
				if (workflowCleanupCallbacks.has(key)) {
					workflowCleanupCallbacks.delete(key);
				}
			}
		} else {
			// 清理整个工作流的数据
			if (key === workflowId || key.startsWith(`${workflowId}_`)) {
				workflowDataStores.delete(key);
				if (workflowCleanupCallbacks.has(key)) {
					workflowCleanupCallbacks.delete(key);
				}
			}
		}
	}
}

// 导出获取存储统计信息的函数
export function getDataStoreStats() {
	const stats = {
		totalStores: workflowDataStores.size,
		stores: [] as any[],
	};

	for (const [storeKey, dataStore] of workflowDataStores) {
		stats.stores.push({
			storeKey,
			itemCount: dataStore.size,
			keys: Array.from(dataStore.keys()),
		});
	}

	return stats;
}
